﻿using DataAccessLayer;
using GlobalObjects;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Channels;
using System.ServiceModel.Web;
using System.Text;
using WCFServiceWebRole1.DataObjects;
using System.Web.Script.Serialization;

namespace WCFServiceWebRole1.Services
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Chart" in code, svc and config file together.
    // NOTE: In order to launch WCF Test Client for testing this service, please select Chart.svc or Chart.svc.cs at the Solution Explorer and start debugging.

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
                 ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class Chart : IChart
    {

        public static Uri baseUri = new Uri("http://uclwebservicetest.cloudapp.net");
        public static string defaultConnectionString = "mongodb://uclmongovm.cloudapp.net:27017";
        public static string defaultDatabase = "test";
        public static UserEntity userEntity = new UserEntity();
        public static DeviceEntity deviceEntity = new DeviceEntity();
        public static SensorEntity sensorEntity = new SensorEntity();
        public static Mongo mongoEntity = new Mongo(defaultConnectionString,defaultDatabase);

        public SensorDataGetPageInfoContract getSensorDataPagingInfo(int userid, int sensorid, string start, string end, int pagesize)
        {
            List<QueryEntity> pagelist;
            DateTime startdate;
            DateTime enddate;
            //Check whether user can access the sensor
            try
            {
                Device device = deviceEntity.getDeviceById_DAL(userid, sensorEntity.getSensorById_DAL(sensorid).Deviceid);
            }
            catch (Exception ex)
            {
                ErrorData errordata = new ErrorData("Given user not authorized to access given sensor"+ex.Message);
                errordata.StackTrace = ex.StackTrace;
                throw new WebFaultException<ErrorData>(errordata, HttpStatusCode.BadRequest);
            }

            CultureInfo ukCulture = new CultureInfo("en-GB");
            try
            {
                 startdate = DateTime.Parse(start, ukCulture.DateTimeFormat);
                 enddate = DateTime.Parse(end, ukCulture.DateTimeFormat);
            }
            catch(Exception ex){
            //if (!DateTime.TryParse(start, out startdate) || !DateTime.TryParse(end, out enddate))
            //{
                ErrorData errordata = new ErrorData("Invalid Start or End Time format. Send UTC Time. UK Date Format"+ex.Message);
                errordata.StackTrace = ex.StackTrace;
                throw new WebFaultException<ErrorData>(errordata, HttpStatusCode.BadRequest);
            }

            //check whether start time is earlier than end time
            if (startdate > enddate)
            {
                ErrorData errordata = new ErrorData("Start Time cannot be later than end time");
                throw new WebFaultException<ErrorData>(errordata, HttpStatusCode.BadRequest);
            }

            //check whether start and end time before current time
            if (startdate > DateTime.UtcNow || enddate > DateTime.UtcNow)
            {
                ErrorData errordata = new ErrorData("Start Time or end time later than current time");
                throw new WebFaultException<ErrorData>(errordata, HttpStatusCode.BadRequest);
            }

            try
            {
                //get the sensor type to identify collection
                string sensortype = sensorEntity.getTypeById_DAL(sensorid);
                //get paging information from the repository 
                pagelist = mongoEntity.getDataPages_DAL(sensorid, startdate, enddate, pagesize, sensortype);
            }
            catch (Exception ex)
            {
                ErrorData errordata = new ErrorData("page Info Retrieval Failed."+ ex.Message);
                errordata.StackTrace = ex.StackTrace;
                throw new WebFaultException<ErrorData>(errordata, HttpStatusCode.BadRequest);
            }
            //return the paging information to the client
            SensorDataGetPageInfoContract response = new SensorDataGetPageInfoContract();
            foreach (var page in pagelist)
            {
                StringBuilder path = new StringBuilder();
                path.Append("Services/");    
                path.Append("Chart.svc/");               
                path.Append("sensordata/pagedata?userid=" + userid);
                path.Append("&sensorid=" + sensorid);
                path.Append("&start=" + page.StartTime);
                path.Append("&end=" + page.EndTime);
                path.Append("&pagesize=" + page.PageSize);
                Uri pageinfo = new Uri(baseUri, path.ToString());
                response.PageData.Add(pageinfo);
            }
            return response;
        }


        public string getSensorDataByPagingUrl(int userid, int sensorid, string start, string end, int pagesize)
        {
            String response = null;
            //Check if the dates are in proper format


            DateTime startdate = DateTime.Parse(start, System.Globalization.CultureInfo.GetCultureInfo("en-us"));
            DateTime enddate = DateTime.Parse(end, System.Globalization.CultureInfo.GetCultureInfo("en-us"));


            //if (!DateTime.TryParse(start, out startdate) || !DateTime.TryParse(start, out enddate))
            //{
            //    ErrorData errordata = new ErrorData("Invalid Start or End Time format. Send UTC Format.");
            //    throw new WebFaultException<ErrorData>(errordata, HttpStatusCode.NoContent);
            //}

            try
            {
                string sensortype = sensorEntity.getTypeById_DAL(sensorid);
                response = mongoEntity.getTempAndHumadityByIdandTime_DAL(sensorid, startdate, enddate, pagesize, sensortype);

                //JavaScriptSerializer js2 = new JavaScriptSerializer();
               //response = js2.Deserialize<string>(response1);
            }
            catch (Exception ex)
            {
                ErrorData errordata = new ErrorData("Data Retrieval Failed"+ex.Message);
                errordata.StackTrace = ex.StackTrace;
                throw new WebFaultException<ErrorData>(errordata, HttpStatusCode.NoContent);
            }
            return response;
        }



        public string testping(int sensorid)
        {
            //Get the ipaddress of the device from the http request
            OperationContext context = OperationContext.Current;
            MessageProperties messageProperties = context.IncomingMessageProperties;
            RemoteEndpointMessageProperty endpointProperty =
              messageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
            string ipaddress = endpointProperty.Address.ToString();
            return LocalPing(IPAddress.Parse(ipaddress),sensorid);
        }
        public string LocalPing(IPAddress address,int sensorid)
        {
            // Ping's the local machine.
            Ping pingSender = new Ping();
            //   IPAddress address = IPAddress.Loopback;
            PingReply reply = pingSender.Send(address);
            StringBuilder response = new StringBuilder();
            if (reply.Status == IPStatus.Success)
            {
                Debug.WriteLine("Address: {0}", reply.Address.ToString());
                response.Append(String.Format("Address: {0}", reply.Address.ToString()));
                Debug.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
                response.Append(String.Format("RoundTrip time: {0}", reply.RoundtripTime));
                Debug.WriteLine("Time to live: {0}", reply.Options.Ttl);
                response.Append(String.Format("Time to live: {0}", reply.Options.Ttl));
                Debug.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
                response.Append(String.Format("Don't fragment: {0}", reply.Options.DontFragment));
                Debug.WriteLine("Buffer size: {0}", reply.Buffer.Length);
                response.Append(String.Format("Buffer size: {0}", reply.Buffer.Length));
                sensorEntity.setSensorStatus_DAL(sensorid, true);
            }
            else
            {
                response.Append(reply.Status);
                Console.WriteLine(reply.Status);
            }
            return response.ToString();
        }
    }
}
